#include "winProcCallBacks.h"
#include "ttMsgMap.h"
#include "ttCalcObjMgr.h"
#include "ttCalcObj_Impl.h"
#include "btnManager.h"
#include "timerManager.h"
#include "timer_Impl.h"

int 
onDefault::runShell(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	return run(hwnd, message, wParam, lParam); 
}

int 
onDefault::run(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	return DefWindowProc(hwnd, message, wParam, lParam);
}

IMPLFUNC(onSize, WM_SIZE)
{
	ttMsgMap::Get()->m_msglpvar.m_cx = LOWORD(lParam);
	ttMsgMap::Get()->m_msglpvar.m_cy = HIWORD(lParam);
	return 1;
}


IMPLFUNC(onPaint, WM_PAINT)
{
	PAINTSTRUCT ps;
	HDC hdc = BeginPaint(hwnd, &ps);
	HDC hdcMem = CreateCompatibleDC(hdc);
	int cxClient, cyClient;
	cxClient = ttMsgMap::Get()->m_msglpvar.m_cx;
	cyClient = ttMsgMap::Get()->m_msglpvar.m_cy;
	HBITMAP hBitmap = CreateCompatibleBitmap(hdc, cxClient, cyClient);
	SelectObject(hdcMem, hBitmap);

	for (int i = 0; i < ttCalcObjMgr::Get()->length(); ++ i){
		((ttPoint*)ttCalcObjMgr::Get()->getObj(i))->drawLink(hdcMem);
	}
	for (int i = 0; i < ttCalcObjMgr::Get()->length(); ++ i){
		ttCalcObjMgr::Get()->getObj(i)->draw(hdcMem);
	}
	if (ttMsgMap::Get()->m_msglpvar.m_bDragging){
		ttMsgMap::Get()->m_msglpvar.drawDragRect(hdcMem);
	}

	BitBlt(hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY);
	DeleteObject(hBitmap);
	DeleteDC(hdcMem);
	EndPaint(hwnd, &ps);
	return 1;
}

IMPLFUNC(onDestroy, WM_DESTROY)
{
	ttMsgMap::Get()->m_msglpvar.writeAndUnint();
	PostQuitMessage(0);
	return 1;
}

IMPLFUNC(onKeyDown, WM_KEYDOWN)
{
	if (VK_ESCAPE == wParam){  
		DestroyWindow(hwnd);  
	}
	return 1;
}

IMPLFUNC(onCreate, WM_CREATE)
{
	btnManager::Get()->CreateSubWindows(hwnd);
	timerManager::Get()->setTimer(hwnd, 1, new paintTimer);
	ttMsgMap::Get()->m_msglpvar.readAndInit();
	return 1;
}

IMPLFUNC(onLButtonDown, WM_LBUTTONDOWN)
{
	int x = LOWORD(lParam);
	int y = HIWORD(lParam);
	
	/*if (ttMsgMap::Get()->m_msglpvar.m_bDragging){
		for (int i = 0; i < ttCalcObjMgr::Get()->length(); ++ i){
			IttCalcObj *ptc = ttCalcObjMgr::Get()->getObj(i);
			if (ptc->hit(x, y)){
				ptc->dragBegin();
				return 1;
			}
		}
	}*/
	if (ttMsgMap::Get()->m_msglpvar.m_bDragging){
		if (!ttMsgMap::Get()->m_msglpvar.m_bDrawDragRect && 
			!ttMsgMap::Get()->m_msglpvar.m_bDragBegin){
			ttMsgMap::Get()->m_msglpvar.m_bDrawDragRect = true;
			ttMsgMap::Get()->m_msglpvar.m_InitDragRectX = x;
			ttMsgMap::Get()->m_msglpvar.m_InitDragRectY = y;
		}
		else {
			ttMsgMap::Get()->m_msglpvar.m_lastDragX = x;
			ttMsgMap::Get()->m_msglpvar.m_lastDragY = y;
		}
	}
	return 1;
}


IMPLFUNC(onLButtonUp, WM_LBUTTONUP)
{
	int x = LOWORD(lParam);
	int y = HIWORD(lParam);
	if (ttMsgMap::Get()->m_msglpvar.m_bBuilding){
		ttPoint *pttp = new ttPoint;
		pttp->setXY(x, y);
		ttCalcObjMgr::Get()->push(pttp);
	}
	else if (ttMsgMap::Get()->m_msglpvar.m_bBuildingAnd){
		andPoint *pttp = new andPoint;
		pttp->setXY(x, y);
		ttCalcObjMgr::Get()->push(pttp);
	}
	else if (ttMsgMap::Get()->m_msglpvar.m_bBuildingOr){
		orPoint *pttp = new orPoint;
		pttp->setXY(x, y);
		ttCalcObjMgr::Get()->push(pttp);
	}
	else if (ttMsgMap::Get()->m_msglpvar.m_bBuildingNot){
		notPoint *pttp = new notPoint;
		pttp->setXY(x, y);
		ttCalcObjMgr::Get()->push(pttp);
	}
	else if (ttMsgMap::Get()->m_msglpvar.m_bDragging){
		/*for (int i = 0; i < ttCalcObjMgr::Get()->length(); ++ i){
			IttCalcObj *ptc = ttCalcObjMgr::Get()->getObj(i);
			if (ptc->isDragging()){
				ptc->dragOver();
				return 1;
			}
		}*/
		if (ttMsgMap::Get()->m_msglpvar.m_bDrawDragRect){
			ttMsgMap::Get()->m_msglpvar.m_bDrawDragRect = false;
			ttMsgMap::Get()->swaptosmall(ttMsgMap::Get()->m_msglpvar.m_InitDragRectX, ttMsgMap::Get()->m_msglpvar.m_crntDragRectX);
			ttMsgMap::Get()->swaptosmall(ttMsgMap::Get()->m_msglpvar.m_InitDragRectY, ttMsgMap::Get()->m_msglpvar.m_crntDragRectY);
			ttMsgMap::Get()->m_msglpvar.m_bDragBegin = true;
			for (int i = 0; i < ttCalcObjMgr::Get()->length(); ++ i){
				ttPoint *pttp = (ttPoint*) ttCalcObjMgr::Get()->getObj(i);;
				if (ttMsgMap::Get()->m_msglpvar.inRect(pttp->getX(), pttp->getY())){
					pttp->dragBegin();
				}
			}
		}
	}
	else if (ttMsgMap::Get()->m_msglpvar.m_bLinking){
		for (int i = 0; i < ttCalcObjMgr::Get()->length(); ++ i){
			IttCalcObj *ptc = ttCalcObjMgr::Get()->getObj(i);
			if (ptc->hit(x, y)){
				ttPoint *pttp = (ttPoint*) ptc;
				pttp->select();
				ttMsgMap::Get()->m_msglpvar.m_linkArr[ttMsgMap::Get()->m_msglpvar.m_linkcnt ++] = pttp;
				if (2 == ttMsgMap::Get()->m_msglpvar.m_linkcnt){
					if (ttMsgMap::Get()->m_msglpvar.m_linkArr[0] != ttMsgMap::Get()->m_msglpvar.m_linkArr[1]){
						ttMsgMap::Get()->m_msglpvar.m_linkArr[1]->linked(ttMsgMap::Get()->m_msglpvar.m_linkArr[0]);
						ttMsgMap::Get()->m_msglpvar.m_linkArr[0]->link(ttMsgMap::Get()->m_msglpvar.m_linkArr[1]);
					}
					ttMsgMap::Get()->m_msglpvar.m_linkcnt = 0;
					ttMsgMap::Get()->m_msglpvar.m_linkArr[0]->drop();
					ttMsgMap::Get()->m_msglpvar.m_linkArr[1]->drop();

				}
				return 1;
			}
		}
	}
	else if (ttMsgMap::Get()->m_msglpvar.m_bDeleting){
		for (int i = 0; i < ttCalcObjMgr::Get()->length(); ++ i){
			IttCalcObj *ptc = ttCalcObjMgr::Get()->getObj(i);
			if (ptc->hit(x, y)){
				ttPoint *pttp = (ttPoint*) ptc;
				pttp->destroy();
				ttCalcObjMgr::Get()->erase(ptc);
			}
		}
	}
	else if (ttMsgMap::Get()->m_msglpvar.m_bSetVal){
		for (int i = 0; i < ttCalcObjMgr::Get()->length(); ++ i){
			IttCalcObj *ptc = ttCalcObjMgr::Get()->getObj(i);
			if (ptc->hit(x, y)){
				ttPoint *pttp = (ttPoint*) ptc;
				pttp->setVal(!pttp->getVal());
			}
		}
	}
	return 1;
}

IMPLFUNC(onBtnClick, WM_COMMAND)
{
	winBtn *pBtn = btnManager::Get()->getObjByMenu(LOWORD(wParam));
	if (NULL != pBtn){
		pBtn->OnButtonClick();
	}
	return 1;
}

IMPLFUNC(onTimer, WM_TIMER)
{
	timerManager::Get()->onTimer(hwnd, message, wParam, lParam);
	return 1;
}

IMPLFUNC(onMouseMove, WM_MOUSEMOVE)
{
	/*if (ttMsgMap::Get()->m_msglpvar.m_bDragging){
		for (int i = 0; i < ttCalcObjMgr::Get()->length(); ++ i){
			ttPoint *ptc = (ttPoint*)ttCalcObjMgr::Get()->getObj(i);
			if (ptc->isDragging()){
				int x = LOWORD(lParam);
				int y = HIWORD(lParam);
				ptc->setXY(x, y);
				return 1;
			}
		}
	}*/
	int x = LOWORD(lParam);
	int y = HIWORD(lParam);	
	if (ttMsgMap::Get()->m_msglpvar.m_bDragging){
		if (ttMsgMap::Get()->m_msglpvar.m_bDrawDragRect){
			ttMsgMap::Get()->m_msglpvar.m_crntDragRectX = x;
			ttMsgMap::Get()->m_msglpvar.m_crntDragRectY = y;
		} else if (ttMsgMap::Get()->m_msglpvar.m_bDragBegin){
			if (-1 != ttMsgMap::Get()->m_msglpvar.m_lastDragX){
				int dx = x - ttMsgMap::Get()->m_msglpvar.m_lastDragX,
					dy = y - ttMsgMap::Get()->m_msglpvar.m_lastDragY;
				ttMsgMap::Get()->m_msglpvar.m_lastDragX = x;
				ttMsgMap::Get()->m_msglpvar.m_lastDragY = y;
				for (int i = 0; i < ttCalcObjMgr::Get()->length(); ++ i){
					ttPoint *ptc = (ttPoint*)ttCalcObjMgr::Get()->getObj(i);
					if (ptc->isDragging()){
						int tx = ptc->getX(), ty = ptc->getY();
						ptc->setXY(tx + dx, ty + dy);
					}
				}
				ttMsgMap::Get()->m_msglpvar.m_InitDragRectX += dx;
				ttMsgMap::Get()->m_msglpvar.m_crntDragRectX += dx;
				ttMsgMap::Get()->m_msglpvar.m_InitDragRectY += dy;
				ttMsgMap::Get()->m_msglpvar.m_crntDragRectY += dy;
			}
		}
	}
	return 1;
}

IMPLFUNC(onRButtonUp, WM_RBUTTONUP)
{
	if (ttMsgMap::Get()->m_msglpvar.m_bDragging){
		ttMsgMap::Get()->m_msglpvar.m_bDragging = false;
		ttMsgMap::Get()->m_msglpvar.m_bDrawDragRect = false;
		ttMsgMap::Get()->m_msglpvar.m_bDragBegin = false;
		ttMsgMap::Get()->m_msglpvar.m_InitDragRectX = -1;
		ttMsgMap::Get()->m_msglpvar.m_InitDragRectY = -1;
		ttMsgMap::Get()->m_msglpvar.m_crntDragRectX = -1;
		ttMsgMap::Get()->m_msglpvar.m_crntDragRectY = -1;
		ttMsgMap::Get()->m_msglpvar.m_lastDragX = -1;
		ttMsgMap::Get()->m_msglpvar.m_lastDragY = -1;
		for (int i = 0; i < ttCalcObjMgr::Get()->length(); ++ i){
			ttPoint *pttp = (ttPoint*)ttCalcObjMgr::Get()->getObj(i);
			pttp->dragOver();
		}
	}
	return 1;
}